package fr.unice.polytech.chord.core;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Entries represents the set of data that are stored by each peer.
 * 
 * @param <T>
 *            the type of the value associated to the Entry.
 * 
 * @author Anthony Parisy
 * @author Laurent Pellegrino
 * @author Marc Valdener
 * 
 * @version 10/28/2009
 */
@SuppressWarnings("serial")
public class Entries<T> implements Iterable<Entry<T>>, Serializable {

	private Map<Key, Entry<T>> entries = new HashMap<Key, Entry<T>>();

	public Entries() {
	}

	/**
	 * Returns all the entries.
	 * 
	 * @return all the entries.
	 */
	public Map<Key, Entry<T>> getEntries() {
		return this.entries;
	}

	/**
	 * Returns an entry by key.
	 * 
	 * @param key
	 *            the key to use in order to find the entry.
	 * @return the entry found or <code>null</code>.
	 */
	public Entry<T> getEntry(Key key) {
		return this.entries.get(key);
	}

	/**
	 * Add all the given entries.
	 * 
	 * @param entries
	 *            the entries to add.
	 */
	public void addAll(Entries<T> entries) {
		this.entries.putAll(entries.getEntries());
	}

	/**
	 * Gets entries that are between two keys.
	 * 
	 * @param from
	 *            lower bound.
	 * @param to
	 *            upper bound.
	 * @return entries checking constraints.
	 */
	public Map<Key, Entry<T>> getEntriesBetween(Key from, Key to) {
		Map<Key, Entry<T>> entriesCheckingConstraints = new HashMap<Key, Entry<T>>();

		Iterator<Key> it = entries.keySet().iterator();
		Key currentKey;

		while (it.hasNext()) {
			currentKey = it.next();

			if (currentKey.compareTo(from) > 0 && currentKey.compareTo(to) <= 0) {
				entriesCheckingConstraints.put(currentKey, new Entry<T>(
						currentKey, entries.get(currentKey).getValue()));
				it.remove();
			}
		}

		return entriesCheckingConstraints;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Iterator<Entry<T>> iterator() {
		return this.entries.values().iterator();
	}

	/**
	 * Removes all the entries.
	 */
	public void clear() {
		this.entries.clear();
	}

	/**
	 * Returns the number of entries managed.
	 * 
	 * @return the number of entries managed.
	 */
	public int size() {
		return this.entries.size();
	}
}
